"""
JavaScript/TypeScript代码处理器 - 专门处理JS/TS文件的优化
"""

import re
from pathlib import Path
from typing import Dict, Any, List, Tuple, Optional

class JavaScriptHandler:
    """JavaScript/TypeScript代码处理器类"""
    
    def __init__(self, path: Path, config: Dict[str, Any]):
        self.path = path
        self.config = config
        self.content = None
        self.lines = []
        self.imports = set()
        self.exports = set()
        self.functions = []
        self.classes = []
        self.is_typescript = path.suffix in ['.ts', '.tsx']
    
    def load(self) -> bool:
        """加载文件内容"""
        try:
            with open(self.path, 'r', encoding='utf-8') as f:
                self.content = f.read()
                self.lines = self.content.splitlines()
            return True
        except Exception as e:
            print(f"无法加载文件 {self.path}: {e}")
            return False
    
    def save(self, path: Optional[str] = None) -> bool:
        """保存文件内容"""
        save_path = Path(path) if path else self.path
        try:
            save_path.parent.mkdir(parents=True, exist_ok=True)
            with open(save_path, 'w', encoding='utf-8') as f:
                if self.content:
                    f.write(self.content)
                else:
                    f.write('\n'.join(self.lines))
            return True
        except Exception as e:
            print(f"无法保存文件 {save_path}: {e}")
            return False
    
    def analyze(self) -> bool:
        """分析JavaScript/TypeScript代码"""
        if not self.load():
            return False
            
        try:
            # 分析导入语句
            import_pattern = r'(?:import|require)\s*\(?[\s\S]*?[\'"](.+?)[\'"]'
            self.imports = set(re.findall(import_pattern, self.content))
            
            # 分析导出语句
            export_pattern = r'export\s+(?:default\s+)?(?:const|let|var|function|class|interface)?\s*(\w+)'
            self.exports = set(re.findall(export_pattern, self.content))
            
            # 分析函数定义
            self._analyze_functions()
            
            # 分析类定义
            self._analyze_classes()
            
            return True
            
        except Exception as e:
            print(f"分析JavaScript/TypeScript文件时出错 {self.path}: {e}")
            return False
    
    def _analyze_functions(self):
        """分析函数定义"""
        # 匹配函数声明和箭头函数
        patterns = [
            r'(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\([^)]*\)',  # 普通函数
            r'(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)\s*=>',  # 箭头函数
            r'(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function\s*\([^)]*\)'  # 函数表达式
        ]
        
        for pattern in patterns:
            for match in re.finditer(pattern, self.content):
                line_no = self.content[:match.start()].count('\n') + 1
                self.functions.append({
                    'name': match.group(1),
                    'line': line_no,
                    'is_async': 'async' in match.group(0),
                    'is_export': 'export' in match.group(0)
                })
    
    def _analyze_classes(self):
        """分析类定义"""
        # 匹配类定义
        class_pattern = r'(?:export\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?'
        
        for match in re.finditer(class_pattern, self.content):
            line_no = self.content[:match.start()].count('\n') + 1
            class_info = {
                'name': match.group(1),
                'line': line_no,
                'is_export': 'export' in match.group(0),
                'base_class': match.group(2) if match.group(2) else None,
                'methods': []
            }
            
            # 查找类的方法
            class_content = self._get_class_content(line_no)
            if class_content:
                method_pattern = r'(?:async\s+)?(\w+)\s*\([^)]*\)'
                for method_match in re.finditer(method_pattern, class_content):
                    class_info['methods'].append({
                        'name': method_match.group(1),
                        'is_async': 'async' in method_match.group(0)
                    })
            
            self.classes.append(class_info)
    
    def _get_class_content(self, start_line: int) -> Optional[str]:
        """获取类定义的内容"""
        class_lines = []
        brace_count = 0
        in_class = False
        
        for line in self.lines[start_line-1:]:
            if '{' in line and not in_class:
                in_class = True
            
            if in_class:
                class_lines.append(line)
                brace_count += line.count('{') - line.count('}')
                
                if brace_count == 0:
                    break
        
        return '\n'.join(class_lines) if class_lines else None
    
    def needs_splitting(self) -> bool:
        """检查文件是否需要拆分"""
        return len(self.lines) > self.config['split_threshold']
    
    def split_file(self) -> List[Tuple[str, str]]:
        """拆分大型JavaScript/TypeScript文件"""
        if not self.needs_splitting():
            return []
        
        # 收集导入语句
        imports = []
        for line in self.lines:
            if re.match(r'^.*(?:import|require).*$', line):
                imports.append(line)
        
        result = []
        extension = '.ts' if self.is_typescript else '.js'
        
        # 创建主文件
        main_content = '\n'.join(imports) + '\n\n'
        
        # 为每个类创建单独的文件
        for class_info in self.classes:
            class_name = class_info['name']
            class_file = f"{class_name.lower()}{extension}"
            
            # 获取类的完整内容
            class_content = self._get_class_content(class_info['line'])
            if class_content:
                class_file_content = '\n'.join(imports) + '\n\n'
                if class_info['is_export']:
                    class_file_content += class_content
                else:
                    class_file_content += 'export ' + class_content
                
                result.append((class_file, class_file_content))
                main_content += f"export {{ {class_name} }} from './{class_name.lower()}';\n"
        
        # 为函数创建单独的文件
        if self.functions:
            functions_content = '\n'.join(imports) + '\n\n'
            export_statements = []
            
            for func in self.functions:
                # 获取函数的完整内容
                func_content = self._get_function_content(func)
                if func_content:
                    if not func['is_export']:
                        func_content = 'export ' + func_content
                    functions_content += func_content + '\n\n'
                    export_statements.append(func['name'])
            
            if export_statements:
                result.append((f"functions{extension}", functions_content))
                main_content += f"\nexport {{ {', '.join(export_statements)} }} from './functions';\n"
        
        # 添加主文件
        result.append((f"index{extension}", main_content))
        
        return result
    
    def _get_function_content(self, func: Dict) -> Optional[str]:
        """获取函数的完整内容"""
        start_line = func['line'] - 1
        func_lines = []
        brace_count = 0
        in_function = False
        
        for line in self.lines[start_line:]:
            if '{' in line and not in_function:
                in_function = True
            
            func_lines.append(line)
            
            if in_function:
                brace_count += line.count('{') - line.count('}')
                if brace_count == 0:
                    break
            elif '=>' in line and line.strip().endswith('{'):
                in_function = True
                brace_count = 1
            elif '=>' in line and ';' in line:
                # 单行箭头函数
                break
        
        return '\n'.join(func_lines) if func_lines else None
    
    def add_async_support(self) -> bool:
        """添加异步支持"""
        if not self.content:
            return False
        
        modified_content = self.content
        
        # 将适合的函数转换为异步函数
        for func in self.functions:
            if not func['is_async'] and self._can_be_async(func):
                # 找到函数定义
                func_content = self._get_function_content(func)
                if func_content:
                    # 添加async关键字
                    if 'function' in func_content:
                        new_func_content = func_content.replace('function', 'async function')
                    elif '=>' in func_content:
                        new_func_content = func_content.replace('(', 'async (')
                    else:
                        continue
                    
                    modified_content = modified_content.replace(func_content, new_func_content)
        
        self.content = modified_content
        return True
    
    def _can_be_async(self, func: Dict) -> bool:
        """判断函数是否适合转换为异步"""
        name = func['name'].lower()
        return any(keyword in name for keyword in [
            'get', 'fetch', 'load', 'download', 'upload',
            'read', 'write', 'save', 'process', 'request'
        ])
    
    def add_performance_monitoring(self) -> bool:
        """添加性能监控代码"""
        if not self.content:
            return False
        
        modified_content = self.content
        
        # 为每个函数添加性能监控
        for func in self.functions:
            func_content = self._get_function_content(func)
            if not func_content:
                continue
            
            # 创建带有性能监控的新函数内容
            indent = len(func_content) - len(func_content.lstrip())
            indent_str = ' ' * indent
            
            # 准备监控代码
            monitor_start = f"\n{indent_str}  const startTime = performance.now();"
            monitor_end = (
                f"\n{indent_str}  const endTime = performance.now();"
                f"\n{indent_str}  console.log(`函数 {func['name']} 执行时间: ${{endTime - startTime}}ms`);"
            )
            
            # 在函数体开始处插入监控开始代码
            body_start = func_content.find('{') + 1
            if body_start > 0:
                new_content = (
                    func_content[:body_start] +
                    monitor_start +
                    func_content[body_start:]
                )
                
                # 在返回语句前插入监控结束代码
                # 这是一个简化的实现，实际上需要处理多个可能的返回点
                if 'return' in new_content:
                    return_pos = new_content.rfind('return')
                    if return_pos > -1:
                        new_content = (
                            new_content[:return_pos] +
                            monitor_end +
                            '\n' + indent_str +
                            new_content[return_pos:]
                        )
                else:
                    # 如果没有返回语句，在函数末尾添加监控结束代码
                    last_brace = new_content.rfind('}')
                    if last_brace > -1:
                        new_content = (
                            new_content[:last_brace] +
                            monitor_end +
                            new_content[last_brace:]
                        )
                
                modified_content = modified_content.replace(func_content, new_content)
        
        self.content = modified_content
        return True
    
    def optimize(self) -> bool:
        """优化JavaScript/TypeScript代码"""
        if not self.analyze():
            return False
        
        # 检查是否需要拆分文件
        if self.needs_splitting():
            split_files = self.split_file()
            if split_files:
                # 创建新的目录来存放拆分后的文件
                module_dir = self.path.parent / self.path.stem
                module_dir.mkdir(exist_ok=True)
                
                # 保存拆分后的文件
                for filename, content in split_files:
                    with open(module_dir / filename, 'w', encoding='utf-8') as f:
                        f.write(content)
                
                print(f"文件已拆分到目录: {module_dir}")
                return True
        
        # 添加异步支持
        if self.config['add_async']:
            self.add_async_support()
        
        # 添加性能监控
        if self.config['monitor']:
            self.add_performance_monitoring()
        
        # 保存修改后的文件
        return self.save()